/* eslint-disable no-nested-ternary */
import {
  ref,
  VNode,
  PropType,
  onMounted,
  onUnmounted,
  defineComponent,
} from 'vue';
import { useUIStore, useNamespace } from '@ibiz-template/vue3-util';
import {
  Modal,
  ViewMode,
  IModalData,
  IOverlayContainer,
} from '@ibiz-template/runtime';
import interact from 'interactjs';
import { isNumber } from 'lodash-es';
import { listenJSEvent } from '@ibiz-template/core';
import { CustomOverlayContainer } from '../custom-overlay-container/custom-overlay-container';
import { IDrawerOptions } from '../../interface';
import './app-drawer-component.scss';

export const AppDrawerComponent = defineComponent({
  props: {
    opts: {
      type: Object as PropType<IDrawerOptions>,
      default: () => ({}),
    },
  },
  setup(props, ctx) {
    const ns = useNamespace('drawer');

    const isShow = ref(false);

    let data: IData;

    const { zIndex } = useUIStore();
    const drawerZIndex = zIndex.increment();

    const calcStyle = (value: number): string => {
      return value > 100 ? `${value}px` : `${value}%`;
    };

    const { placement = 'right', width, height } = props.opts;

    /**
     * 抽屉样式
     */
    const drawerStyle = {
      zIndex: drawerZIndex,
      height: ['top', 'bottom'].includes(placement)
        ? isNumber(height)
          ? calcStyle(height)
          : '30%'
        : '100%',
      width: ['top', 'bottom'].includes(placement)
        ? '100%'
        : isNumber(width)
          ? calcStyle(width)
          : '30%',
    };

    const modal = new Modal({
      mode: ViewMode.DRAWER,
      viewUsage: 2,
      dismiss: (_data: IModalData): void | undefined => {
        zIndex.decrement();
        isShow.value = false;
        data = _data;
        ctx.emit('dismiss', data);
      },
    });

    /**
     * 关闭抽屉外部调用
     * - 外部函数式调用
     */
    const dismiss = (_data?: IModalData): void => {
      modal.dismiss(_data);
    };

    /**
     * 显示抽屉外部调用
     * - 外部函数式调用
     */
    const present = (): void => {
      isShow.value = true;
    };

    /**
     * 关闭抽屉
     *
     */
    const onClosed = async (): Promise<void> => {
      await modal.dismiss();
    };

    /**
     * 点击遮罩关闭抽屉
     *
     */
    const onClickModal = (): void => {
      if (props.opts.closeOnClickModal !== false) {
        onClosed();
      }
    };

    /**
     * ESC关闭抽屉
     *
     * @param {KeyboardEvent} event
     */
    const listener = (event: KeyboardEvent): void => {
      if (event.code === 'Escape' && props.opts.closeOnPressEscape !== false) {
        onClosed();
      }
    };

    const cleanup = listenJSEvent(window, 'keydown', listener, {
      capture: true,
    });

    /**
     * 拖拽边
     *
     */
    const dragBorder = (): void => {
      interact('.ibiz-drawer__body').resizable({
        edges: {
          top: ['bottom', 'left', 'right'].includes(placement),
          left: ['right', 'top', 'bottom'].includes(placement),
          bottom: ['top', 'left', 'right'].includes(placement),
          right: ['left', 'top', 'bottom'].includes(placement),
        },
        listeners: {
          move: event => {
            const style = {
              top: `${event.rect.top}px`,
              left: `${event.rect.left}px`,
              right: `${event.rect.right}px`,
              bottom: `${event.rect.bottom}px`,
              width: `${event.rect.width}px`,
              height: `${event.rect.height}px`,
            };
            Object.assign(event.target.style, style);
          },
          start: () => {
            // 禁止选择文本，避免拖动时出现选择效果
            document.body.style.userSelect = 'none';
          },
          end: () => {
            // 恢复选择文本功能
            document.body.style.userSelect = '';
          },
        },
        modifiers: [
          // 保持在父对象内部
          interact.modifiers.restrictEdges({ outer: document.body }),
        ],
      });
    };

    onMounted(() => {
      if(props.opts.dragBorder !== false) dragBorder();
    });

    onUnmounted(() => {
      cleanup();
    });

    return {
      ns,
      modal,
      isShow,
      placement,
      drawerStyle,
      dismiss,
      present,
      onClosed,
      onClickModal,
    };
  },
  render() {
    return (
      <div class={[this.ns.b(), this.ns.is('show', this.isShow)]}>
        {this.opts.modal && (
          <div
            class={[this.ns.e('overlay'), this.opts.modalClass]}
            onClick={this.onClickModal}
            style={{ zIndex: this.drawerStyle.zIndex - 1 }}
          ></div>
        )}
        <div
          class={[
            this.ns.e('body'),
            this.opts.customClass,
            this.ns.em('body', this.placement),
            this.ns.is('show-close', this.opts.showClose),
          ]}
          style={this.drawerStyle}
        >
          {this.opts.showClose && (
            <ion-icon
              title='关闭'
              name='close-outline'
              onClick={this.onClosed}
              class={this.ns.em('icon', 'close')}
            ></ion-icon>
          )}
          {this.$slots.default?.(this.modal)}
        </div>
      </div>
    );
  },
});

/**
 * 创建抽屉
 *
 * @author chitanda
 * @date 2022-12-29 15:12:57
 * @export
 * @param {() => VNode} render
 * @param {(IDrawerOptions | undefined)} [opts]
 * @return {*}  {IOverlayContainer}
 */
export function createDrawer(
  render: () => VNode,
  opts: IDrawerOptions = {},
  props: IParams = {},
): IOverlayContainer {
  return new CustomOverlayContainer(AppDrawerComponent, render, opts, props);
}
